package com.cooldatasoft.securityImpl;

import java.io.Serializable;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.AccountStatusException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.openid.OpenIDAttribute;
import org.springframework.security.openid.OpenIDAuthenticationToken;
import org.springframework.security.web.authentication.logout.LogoutHandler;

import com.cooldatasoft.domain.dao.UserDao;
import com.cooldatasoft.domain.model.User;
import com.cooldatasoft.exception.TaskManagerException;
import com.cooldatasoft.exception.TaskManagerUserException;
import com.cooldatasoft.security.TaskManagerSecurityManager;
import com.cooldatasoft.support.TaskManagerUserDetails;



public class TaskManagerSecurityManagerImpl implements TaskManagerSecurityManager, Serializable { 

	private static final long serialVersionUID = -3013065619624760200L;

	private static final Logger logger = Logger.getLogger(TaskManagerSecurityManagerImpl.class);

	@Autowired
	private UserDao userDao;

	@Autowired
	private AuthenticationManager authenticationManager;
	
	@Autowired
	private LogoutHandler logoutHandler;

	public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException, DataAccessException {
		logger.debug("loadUserByUsername(String email): " + email);

		User user = null;
	
		user = userDao.getUserByEmail(email);
		logger.debug("user: " + user);
		
		if (user == null) {
			user = new User();
		}
		TaskManagerUserDetails userDetails = new TaskManagerUserDetails(user);

		return userDetails;
	}
	
	public User getCurrentUser() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

		if (authentication != null && authentication.getPrincipal() instanceof TaskManagerUserDetails) {
			return ((TaskManagerUserDetails) authentication.getPrincipal()).getCurrentUser();
		} 
		
		return null;		
	}

	public Boolean isAuthenticated() { 
		return true;
	}
	
	public Boolean login(String email, String password) throws TaskManagerException {
		try {

			Authentication authRequest = new UsernamePasswordAuthenticationToken(email, password);
			Authentication auth = authenticationManager.authenticate(authRequest);
			SecurityContextHolder.getContext().setAuthentication(auth);
			return auth.isAuthenticated();

		} catch (AccountStatusException e) {
			throw new TaskManagerUserException("login.exception.DisabledException", "Účet nie je aktivovaný");
		} catch (BadCredentialsException e) {			
			throw new TaskManagerUserException("login.exception.BadCredentialsException", "Zadané meno a heslo je nesprávne");
		} catch (AuthenticationException e) {
			throw new TaskManagerUserException("login.exception.AuthenticationException", "Prihlásenie sa nepodarilo");
		} catch (Exception e) {
			throw new TaskManagerException(e.getMessage(), e);
		}
	}
	
	public void logout(HttpServletRequest req, HttpServletResponse resp) {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		logoutHandler.logout(req, resp, auth);
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

	@Override
	public UserDetails loadUserDetails(OpenIDAuthenticationToken token)
			throws UsernameNotFoundException {
		String id = token.getIdentityUrl();
        String email = null;
        String firstName = null;
        String lastName = null;
        List<OpenIDAttribute> attributes = token.getAttributes();
        for (OpenIDAttribute attribute : attributes) {
            if (attribute.getName().equals("email")) {
                email = attribute.getValues().get(0);
            }
            if (attribute.getName().equals("firstname")) {
                firstName = attribute.getValues().get(0);
            }
            if (attribute.getName().equals("lastname")) {
                lastName = attribute.getValues().get(0);
            }
        }
        
        User user = userDao.getUserByPassword(id);
        if(user == null){
	        user = new User();
	        user.setEmail(email);
	        user.setName(firstName);
	        user.setSurname(lastName);
	        user.setActivated(true);
	        user.setSpecialties("programmer");
	        user.setPassword(id);
	        userDao.insert(user);
        }
        
        TaskManagerUserDetails taskManagerUserDetails = new TaskManagerUserDetails(user);     
        
        return taskManagerUserDetails;
	}
}
